package com.naiterui.ehp.bs.pc.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.naiterui.ehp.bp.support.exception.BaseExceptionCodes;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bs.pc.common.constants.CacheConstants;
import com.naiterui.ehp.bs.pc.common.entity.BaseEntity;
import com.naiterui.ehp.bs.pc.common.vo.PageParamsVO;
import com.naiterui.ehp.bs.pc.common.vo.PageVO;
import com.naiterui.ehp.bs.pc.modules.sys.entity.Dept;
import com.naiterui.ehp.bs.pc.modules.sys.entity.Role;
import com.naiterui.ehp.bs.pc.modules.sys.mapper.RoleMapper;
import com.naiterui.ehp.bs.pc.modules.sys.service.IDeptService;
import com.naiterui.ehp.bs.pc.modules.sys.service.IRoleDeptService;
import com.naiterui.ehp.bs.pc.modules.sys.service.IRoleMenuService;
import com.naiterui.ehp.bs.pc.modules.sys.service.IRoleService;
import com.naiterui.ehp.bs.pc.modules.sys.service.IUserRoleService;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 角色
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

  @Autowired
  private IRoleMenuService roleMenuService;
  @Autowired
  private IRoleDeptService roleDeptService;
  @Autowired
  private IUserRoleService userRoleService;
  @Autowired
  private IDeptService deptService;

  @Override
  public Role getRoleInfo(Long roleId) {
    Role role = super.getById(roleId);
    // 查询角色对应的菜单
    List<Long> menuIdList = this.roleMenuService.queryMenuIdList(roleId);
    role.setMenuIdList(menuIdList);
    return role;
  }

  @Override
  public PageVO<Role> queryPage(PageParamsVO pageParamsVO, Role role) {
    IPage<Role> page = this.page(pageParamsVO.getPage(), pageParamsVO.getEntityWrapper(role));
    page.getRecords().forEach(entity -> {
      Dept dept = this.deptService.getById(entity.getDeptId());
      if (dept != null) {
        entity.setDeptName(dept.getName());
      }
    });
    return PageVO.toPageVo(page);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean save(Role role) {
    boolean save = super.save(role);
    // 保存角色与菜单关系
    this.roleMenuService.saveOrUpdate(role.getId(), role.getMenuIdList());
    return save;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  @CacheEvict(value = {CacheConstants.MENU_LIST, CacheConstants.USER_MENU_LIST, CacheConstants.USER,
      CacheConstants.PERMISSION_CACHE_PREFIX}, allEntries = true)
  public void update(Role role) {
    Long id = role.getId();
    Preconditions.checkNotNull(id, "角色ID不能为null");
    // 如果修改了部门部门，那么要清空
    Long deptId = this.baseMapper.getDeptIdById(id);
    if (!Objects.equals(deptId, role.getDeptId())) {
      // 删除角色与用户关联
      this.userRoleService.deleteBatch(new Long[]{id});
    }
    super.updateById(role);
    // 更新角色与菜单关系
    this.roleMenuService.saveOrUpdate(id, role.getMenuIdList());
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  @CacheEvict(value = {CacheConstants.MENU_LIST, CacheConstants.USER_MENU_LIST, CacheConstants.USER,
      CacheConstants.PERMISSION_CACHE_PREFIX}, allEntries = true)
  public void deleteBatch(Long[] roleIds) {
    // 删除角色
    super.removeByIds(Arrays.asList(roleIds));
    // 删除角色与菜单关联
    this.roleMenuService.deleteBatch(roleIds);
    // 删除角色与部门关联
    this.roleDeptService.deleteBatch(roleIds);
    // 删除角色与用户关联
    this.userRoleService.deleteBatch(roleIds);
  }

  @Override
  public List<Role> selectBatchIds(List<Long> roleIdList) {
    return this.baseMapper.selectBatchIds(roleIdList);
  }

  @Override
  public void checkRole(Long deptId, List<Long> roleIdList) throws BusinessException {
    Map<Long, List<Role>> deptRoleMap = this.getSelect();
    List<Role> roles = deptRoleMap.get(deptId);
    if (CollectionUtils.isEmpty(roles)) {
      throw new BusinessException(BaseExceptionCodes.FAILED, "当前部门下暂时没有角色。");
    }
    List<Long> deptRoleIds = roles.stream().map(BaseEntity::getId).collect(Collectors.toList());
    if (!deptRoleIds.containsAll(roleIdList)) {
      throw new BusinessException(BaseExceptionCodes.FAILED, "当前角色校验不通过。");
    }

  }

  @Override
  public Map<Long, List<Role>> getSelect() {
    List<Role> roles = this.baseMapper.getSelect();
    Map<Long, List<Role>> groupByRoles = roles.stream().collect(Collectors.groupingBy(Role::getDeptId));
    List<Dept> depts = this.deptService.list();
    Map<Long, List<Role>> collect = depts.stream()
        .map(BaseEntity::getId)
        .collect(Collectors.toMap(Function.identity(), deptId -> this.getRolesByDeptId(deptId, groupByRoles),
            (a, b) -> b));
    collect.put(-1L, roles);
    return collect;

  }

  private List<Role> getRolesByDeptId(Long deptId, Map<Long, List<Role>> groupByRoles) {
    List<Role> roles = Lists.newArrayList();
    List<Long> deptIds = this.deptService.getIdByPatientId(deptId);
    deptIds.stream().map(groupByRoles::get).filter(roleList -> !CollectionUtils.isEmpty(roleList)).forEach(roles::addAll);
    return roles;
  }

}
